home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / pas / swag / win_os2.swg / 0025_New EXE Headers.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-26  |  13KB  |  313 lines

  1. (*
  2. In article 767298319@stimpy.cs.iastate.edu, james@cs.iastate.edu (James N. Potts) writes:
  3. >I know that if you place {$D string} in a program, the string will be placed
  4. >into the executable.  Is there an easy way to find this information, or do
  5. >you have to do a search through the file?
  6.  
  7. There are a few ways.  Screen savers use this information, so one way
  8. to do it is to rename your file *.scr, place it in the windows directory,
  9. and then look at it from the control panel as you are selecting a screen
  10. saver.  Yeach!  Another way is to use a file dumper (?) such as
  11. TDUMP by Borland or EXEHDR by Microsoft.  These programs will give you
  12. the pertinent information.  TDUMP by the way comes with BP 7.0.
  13.  
  14. Programmaticly you can obtain the string through the new executable
  15. file header information.  The string you are interested in is the
  16. first entry in the nonresident-name table.  If you do not specify
  17. {$D string} then this string will be the file name (like myfile.EXE).
  18.  
  19. A few days ago I posted how to do certain things with the new executable
  20. file header.  You may want to look back a few days on your news reader
  21. to get some insight.  But don't dispare.  I will give some clues here.
  22.  
  23. The first thing to do is to read the new EXE file format found
  24. in the Borland or Micrsoft help files.  For Borland it can
  25. be found under the "File Formats" topic.
  26.  
  27. Next you should get the EXE header types.  This can be obtained
  28. at ftp.microsoft.com (filename: newexe12.zip).  I have
  29. included a Pascal version at the end of this missive.
  30.  
  31. Now in your program you need to do the following:
  32.  
  33.   1.  Determine if the file is of the new EXE type.
  34.   2.  Get the address of the non-resident name table.
  35.   3.  Read the first string in the non-resident name table.
  36.  
  37. Later in this missive you will find a function that does step 1.
  38. Below are the steps
  39. *)
  40.  
  41. uses
  42.   WinCrt,
  43.   WinTypes,
  44.   WinProcs;
  45.  
  46. const
  47.   fn: PChar = 'c:\bp\myprog\myprog.exe';
  48.  
  49. type
  50.   DosHdr           : IMAGE_DOS_HEADER;
  51.   NewHdr           : IMAGE_NEW_HEADER;
  52.   ModuleDescription: rsrc_string;
  53.   Filehandle       : Integer;
  54.   ofs              : TOFSTRUCT;
  55.  
  56. label
  57.   Return;
  58.  
  59. begin
  60. if not IsNewExe (fn, DosHdr, NewHdr) then goto Return;
  61.  
  62. FillChar (ofs, sizeof (TOFSTRUCT), 0);
  63. if OpenFile (fn, ofs, OF_EXIST or OF_READ) = -1 then goto Return;
  64.  
  65. FileHandle := OpenFile (fn, ofs, OF_REOPEN or OF_READ);
  66. if FileHandle = -1 then goto Return;
  67.  
  68. { goto location of non-resident name table }
  69. _llseek (FileHandle, DosHdr.e_lfanew + NewHdr.ne_nrestab, 0);
  70.  
  71. { read length of string (in first entry of the non-resident name table) }
  72. _lread (FileHandle, @ModuleDescription.rs_len, sizeof (Byte));
  73.  
  74. { allocate space for string }
  75. GetMem (ModuleDescription.rs_string, ModuleDescription.rs_len + 1);
  76.  
  77. { read module description string }
  78. _lread (FileHandle, @ModuleDescription.rs_string, ModuleDescription.rs_len);
  79.  
  80. { tag null termination onto string }
  81. ModuleDescription.rs_string[ModuleDescription.rs_len] := #0;
  82.  
  83. { write results }
  84. writeln (fn, ' Module Description: ', ModuleDescription.rs_string);
  85.  
  86. { dispose of string }
  87. FreeMem (ModuleDescription.rs_string, ModuleDescription.rs_len + 1);
  88.  
  89. Return:
  90. { close file }
  91. _lclose (FileHandle);
  92. end.
  93.  
  94.  
  95. Note that the above code is only good for finding the first string
  96. in the non-resident name table as the rest of the table also includes
  97. index numbers as wll as the string length and the string.  This code
  98. has also not been tested.
  99.  
  100. I hope you get some mileage from it.
  101.  
  102. -Michael Vincze
  103. vincze@lobby.ti.com
  104.  
  105. ---------- NEW EXE HEADER TYPES ----------
  106.  
  107. type
  108.   IMAGE_DOS_HEADER = record     { DOS 1, 2, 3 .EXE header     }
  109.     e_magic   : Word;     { Magic number                      }
  110.     e_cblp    : Word;     { Words on last page of file        }
  111.     e_cp      : Word;     { Pages in file                     }
  112.     e_crlc    : Word;     { Relocations                       }
  113.     e_cparhdr : Word;     { Size of header in paragraphs      }
  114.     e_minalloc: Word;     { Minimum extra paragraphs needed   }
  115.     e_maxalloc: Word;     { Maximum extra paragraphs needed   }
  116.     e_ss      : Word;     { Initial (relative) SS value       }
  117.     e_sp      : Word;     { Initial SP value                  }
  118.     e_csum    : Word;     { Checksum                          }
  119.     e_ip      : Word;     { Initial IP value                  }
  120.     e_cs      : Word;     { Initial (relative) CS value       }
  121.     e_lfarlc  : Word;     { File address of relocation table  }
  122.     e_ovno    : Word;     { Overlay number                    }
  123.     e_res     : array[0..3] of Word;  { Reserved words        }
  124.     e_oemid   : Word;     { OEM identifier (for e_oeminfo)    }
  125.     e_oeminfo : Word;     { OEM information; e_oemid specific }
  126.     e_res2    : array[0..9] of Word;  { Reserved words        }
  127.     e_lfanew  : Longint;  { File address of new exe header    }
  128.     end;
  129.  
  130. const
  131.   IMAGE_DOS_SIGNATURE    = $00005A4D; { MZ    }
  132.   IMAGE_OS2_SIGNATURE    = $0000454E; { NE    }
  133.   IMAGE_OS2_SIGNATURE_LE = $00005A4D; { LE    }
  134.   IMAGE_NT_SIGNATURE     = $00004550; { PE00  }
  135.  
  136. type
  137.   IMAGE_NEW_HEADER = record { New .EXE header                       }
  138.     ne_magic      : Word;     { Magic number NE_MAGIC               }
  139.     ne_ver        : Byte;     { Version number                      }
  140.     ne_rev        : Byte;     { Revision number                     }
  141.     ne_enttab     : Word;     { Offset of Entry Table               }
  142.     ne_cbenttab   : Word;     { Number of bytes in Entry Table      }
  143.     ne_crc        : Longint;  { Checksum of whole file              }
  144.     ne_flags      : Word;     { Flag word                           }
  145.     ne_autodata   : Word;     { Automatic data segment number       }
  146.     ne_heap       : Word;     { Initial heap allocation             }
  147.     ne_stack      : Word;     { Initial stack allocation            }
  148.     ne_csip       : Longint;  { Initial CS:IP setting               }
  149.     ne_sssp       : Longint;  { Initial SS:SP setting               }
  150.     ne_cseg       : Word;     { Count of file segments              }
  151.     ne_cmod       : Word;     { Entries in Module Reference Table   }
  152.     ne_cbnrestab  : Word;     { Size of non-resident name table     }
  153.     ne_segtab     : Word;     { Offset of Segment Table             }
  154.     ne_rsrctab    : Word;     { Offset of Resource Table            }
  155.     ne_restab     : Word;     { Offset of resident name table       }
  156.     ne_modtab     : Word;     { Offset of Module Reference Table    }
  157.     ne_imptab     : Word;     { Offset of Imported Names Table      }
  158.     ne_nrestab    : Longint;  { Offset of Non-resident Names Table  }
  159.     ne_cmovent    : Word;     { Count of movable ent                }
  160.     ne_align      : Word;     { Segment alignment shift count       }
  161.     ne_cres       : Word;     { Count of resource entries           }
  162.     ne_exetyp     : Byte;     { Target operating system             }
  163.     ne_flagsothers: Byte;     { Other .EXE flags                    }
  164.     ne_res        : array [0..7] of Byte; { Pad structure to 64 bytes }
  165.     end;
  166.  
  167. const { Format of ne_exetyp (target operating system) }
  168.   NE_UNKNOWN = $0;  { Unknown (any "new-format" OS) }
  169.   NE_OS2     = $1;  { Microsoft/IBM OS/2            }
  170.   NE_WINDOWS = $2;  { Microsoft Windows             }
  171.   NE_DOS4    = $3;  { Microsoft MS-DOS 4.x          }
  172.   NE_DEV386  = $4;  { Microsoft Windows 386         }
  173.  
  174. const { Format of IMAGE_NEW_HEADER.ne_flags                     }
  175.   NENOTP         = $8000; { Not a process                       }
  176.   NEIERR         = $2000; { Errors in image                     }
  177.   NEBOUND        = $0800; { Bound as family app                 }
  178.   NEAPPTYP       = $0700; { Application type mask               }
  179.   NENOTWINCOMPAT = $0100; { Not compatible with P.M. Windowing  }
  180.   NEWINCOMPAT    = $0200; { Compatible with P.M.                }
  181.   NEWINAPI       = $0300; { Uses P.M. Windowing API             }
  182.   NEFLTP         = $0080; { Floating-point instructions         }
  183.   NEI386         = $0040; { 386 instructions                    }
  184.   NEI286         = $0020; { 286 instructions                    }
  185.   NEI086         = $0010; { 8086 instructions                   }
  186.   NEPROT         = $0008; { Runs in protected mode only         }
  187.   NEPPLI         = $0004; { Per-Process Library Initialization  }
  188.   NEINST         = $0002; { Instance data                       }
  189.   NESOLO         = $0001; { Solo data                           }
  190.  
  191. type
  192.   new_seg = record  { New .EXE segment table entry        }
  193.     ns_sector  : Word;  { File sector of start of segment }
  194.     ns_cbseg   : Word;  { Number of bytes in file         }
  195.     ns_flags   : Word;  { Attribute flags                 }
  196.     ns_minalloc: Word;  { Minimum allocation in bytes     }
  197.     end;
  198.  
  199. const { Format of new_seg.nsflags                                                 }
  200.   NSCODE    = $0000;  { Code segment                                              }
  201.   NSDATA    = $0001;  { Data segment                                              }
  202.   NSLOADED  = $0004;  { ns_sector field contains memory addr                      }
  203.   NSTYPE    = $0007;  { Segment type mask                                         }
  204.   NSITER    = $0008;  { Iterated segment flag                                     }
  205.   NSMOVE    = $0010;  { Movable segment flag                                      }
  206.   NSSHARED  = $0020;  { Shared segment flag                                       }
  207.   NSPRELOAD = $0040;  { Preload segment flag                                      }
  208.   NSEXRD    = $0080;  { Execute-only (code segment), or  read-only (data segment) }
  209.   NSRELOC   = $0100;  { Segment has relocations                                   }
  210.   NSCONFORM = $0200;  { Conforming segment                                        }
  211.   NSDISCARD = $1000;  { Segment is discardable                                    }
  212.   NS32BIT   = $2000;  { 32-bit code segment                                       }
  213.   HSHUGE    = $4000;  { Huge memory segment                                       }
  214.   NSEXPDOWN = $0200;  { Data segment is expand down                               }
  215.  
  216. (*
  217. #define NSDPL   0x0C00    /* I/O privilege level (286 DPL bits) */
  218. #define SHIFTDPL  10    /* Left shift count for */
  219. #define NSPURE    NSSHARED  /* For compatibility */
  220. #define NSALIGN 9 /* Segment data aligned on 512 byte boundaries */
  221. *)
  222.  
  223. type
  224.   new_rlcinfo = record  { Relocation info                       }
  225.     nr_nreloc: Word;  { number of relocation items that follow  }
  226.     end;
  227.  
  228. type
  229.   new_rlc = record  { Relocation item }
  230.     nr_stype: Byte; { Source type     }
  231.     nr_flags: Byte; { Flag byte       }
  232.     nr_soff : Word; { Source offset   }
  233.     case Integer of
  234.       0: (nr_segno : Byte;  { Target segment number             } { internal reference      }
  235.           nr_res   : Byte;  { Reserved                          }
  236.           nr_entry : Word); { Target Entry Table offset         }
  237.       1: (nr_mod   : Word;  { Index into Module Reference Table } { import                  }
  238.           nr_proc  : Word); { Procedure ordinal or name offset  }
  239.       2: (nr_ostype: Word;  { OSFIXUP type                      } { operating system fixup  }
  240.           nr_osres : Word); { Reserved                          }
  241.     end;
  242.  
  243. { Resource type or name string
  244. }
  245. type
  246.   rsrc_string = record
  247.     rs_len   : Byte;  { number of bytes in string }
  248.     rs_string: PChar; { text of string            }
  249.     end;
  250.  
  251.  
  252. ---------- IsNewExe() function ----------
  253.  
  254. Below is the code to determine if the file is of the new EXE type.
  255. Note how DosHdr and NewHdr are passed by reference and not by value.
  256. This is so values for DosHdr and NewHdr can be used by other
  257. functions called by the main program.  Also note the extensive use
  258. of the OpenFile(), _lread(), _llseek(), and _lclose() functions.
  259.  
  260.   function IsNewExe (fn: PChar;
  261.                      var DosHdr: IMAGE_DOS_HEADER;
  262.                      var NewHdr: IMAGE_NEW_HEADER): Boolean;
  263.   label
  264.     Return;
  265.   var
  266.     Filehandle: Integer;
  267.     BytesRead : Integer;
  268.     ofs       : TOFSTRUCT;
  269.   begin
  270.   IsNewExe := False;
  271.  
  272.   FillChar (ofs, sizeof (TOFSTRUCT), 0);
  273.   if OpenFile (fn, ofs, OF_EXIST or OF_READ) = -1 then goto Return;
  274.  
  275.   FileHandle := OpenFile (fn, ofs, OF_REOPEN or OF_READ);
  276.   if FileHandle = -1 then goto Return;
  277.  
  278.   FillChar (DosHdr, sizeof (IMAGE_DOS_HEADER), 0);
  279.   FillChar (NewHdr, sizeof (IMAGE_NEW_HEADER), 0);
  280.  
  281.   { read MS-DOS header }
  282.   BytesRead := _lread (FileHandle, @DosHdr, sizeof (IMAGE_DOS_HEADER));
  283.  
  284.   { test for bytes read }
  285.   if BytesRead <> sizeof (IMAGE_DOS_HEADER) then goto Return;
  286.  
  287.   { test for magic number MZ }
  288.   if DosHdr.e_magic <> IMAGE_DOS_SIGNATURE then goto Return;
  289.  
  290.   { test for address of new exe header }
  291.   if DosHdr.e_lfanew <= 0 then goto Return;
  292.  
  293.   { fast forward to Windows header }
  294.   if _llseek (FileHandle, DosHdr.e_lfanew, 0) = -1 then goto Return;
  295.  
  296.   { read new exe header }
  297.   BytesRead := _lread (FileHandle, @NewHdr, sizeof (IMAGE_NEW_HEADER));
  298.  
  299.   { test for bytes read }
  300.   if BytesRead <> sizeof (IMAGE_NEW_HEADER) then goto Return;
  301.  
  302.   { test for signature NE }
  303.   if NewHdr.ne_magic <> IMAGE_OS2_SIGNATURE then goto Return;
  304.  
  305.   { passed the test }
  306.   IsNewExe := True;
  307.  
  308.   Return:
  309.   { close file }
  310.   _lclose (FileHandle);
  311.   end;
  312.  
  313.